import re
from datetime import datetime
from math import ceil

from django.contrib.admin.models import LogEntry, ADDITION, DELETION, CHANGE
from django.contrib.auth import authenticate, login, logout
from django.contrib.contenttypes.models import ContentType
from django.contrib.sessions.models import Session
from django.core.paginator import Paginator
from django.shortcuts import get_object_or_404
from django.utils import timezone
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from rest_framework import status
from django.middleware.csrf import get_token
from django.core.cache import cache
from data.models import Product, Image,Coach
from rest_framework.permissions import IsAuthenticated
from data.serializers import ProductSerializer, CoachSerializer
import requests
from django.core.exceptions import ValidationError, ObjectDoesNotExist
import imghdr, os
import pyclamd
import logging

logger = logging.getLogger('admin_actions')

def validate_image_file(file):
    """
    深度校验图片文件安全性
    :param file: InMemoryUploadedFile 对象
    :return: None (校验通过)
    :raises: ValidationError (校验失败)
    """
    # 1. 基本校验
    if not file:
        raise ValidationError("未上传图片文件")

    if file.size > 5 * 1024 * 1024:  # 5MB限制
        raise ValidationError("图片大小不能超过5MB")

    # 2. 文件扩展名校验
    valid_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp']
    ext = os.path.splitext(file.name)[1].lower()
    if ext not in valid_extensions:
        raise ValidationError("不支持的图片格式")

    # 3. 真实文件类型校验（防止伪装扩展名）
    file.seek(0)  # 重要！确保读取文件头
    real_type = imghdr.what(file)
    if not real_type:
        raise ValidationError("无法识别图片格式")

    # 4. 文件头与扩展名匹配校验
    type_map = {
        'jpeg': ['jpg', 'jpeg'],
        'png': ['png'],
        'gif': ['gif'],
        'webp': ['webp']
    }

    # 5. 重置文件指针（重要！）
    file.seek(0)


@api_view(['GET'])
@permission_classes([IsAuthenticated])  # 确保用户已登录
def get_product_detail(request):
    # print(request.user.is_authenticated, request.user.is_staff)
    # 检查用户是否是管理员
    if not request.user.is_staff:
        return Response({
            'status': 'error',
            'message': 'Permission denied. Only admin can access this endpoint.'
        }, status=status.HTTP_403_FORBIDDEN)

    # 获取课程 ID
    product_id = request.GET.get('id')
    if not product_id:
        return Response({
            'status': 'error',
            'message': 'Product ID is required.'
        }, status=status.HTTP_400_BAD_REQUEST)

    try:
        # 查询课程详情
        product = Product.objects.get(id=product_id)
    except Product.DoesNotExist:
        return Response({
            'status': 'error',
            'message': 'Product not found.'
        }, status=status.HTTP_404_NOT_FOUND)

    # 构造返回的数据
    product_data = {
        'id': product.id,
        'productname': product.productname,
        'description': product.description,
        'en_description': product.en_description,
        'subid': product.subid,
        'location': product.location,
        'price': float(product.price),  # 将 Decimal 转换为 float
        'member_price': float(product.member_price),
        'cover_image': product.covar_id.url if product.covar_id else None,
        'created_at': product.created_at,
        'max_times': product.maxtimes
    }

    return Response({'status': 'success', 'data': product_data}, status=status.HTTP_200_OK)


@api_view(['GET'])
@permission_classes([IsAuthenticated])  # 确保用户已登录
def get_product_data(request):
    # 检查用户是否是管理员
    # print(request.user.is_authenticated, request.user.is_staff)
    if not request.user.is_staff:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)
    if not request.user.is_authenticated:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)

    # 获取地点参数
    location = request.GET.get('location', '钟村街道祈福集团中心二楼222单元大羊角运动康复综合馆')

    # 根据地点过滤产品
    products = Product.objects.filter(location=location)

    # 构造返回的数据
    product_list = []
    for product in products:
        product_list.append({
            'id': product.id,
            'productname': product.productname,
            'description': product.description,
            'price': float(product.price),  # 将 Decimal 转换为 float
            'member_price': float(product.member_price),
            'cover_image': product.covar_id.url if product.covar_id else None,
        })

    return Response({'status': 'success', 'data': product_list})


@api_view(['POST'])
def user_login(request):
    if request.method == 'POST':
        data = request.data  # DRF 自动解析请求体
        username = data.get('username')
        password = data.get('password')

        # 检查登录失败次数
        cache_key = f'login_failures_{username}'  # 使用用户名作为缓存键
        failure_count = cache.get(cache_key, 0)

        if failure_count >= 5:
            return Response({
                'status': 'error',
                'message': '登录失败次数过多，请 10 分钟后再试',
            }, status=status.HTTP_429_TOO_MANY_REQUESTS)

        # 验证用户
        user = authenticate(request, username=username, password=password)

        if user is not None:
            # 清除登录失败次数
            cache.delete(cache_key)

            # 清除用户的所有活跃 Session
            sessions = Session.objects.filter(expire_date__gte=timezone.now())
            for session in sessions:
                if session.get_decoded().get('_auth_user_id') == str(user.id):
                    session.delete()

            # 登录用户并创建新的 Session
            login(request, user)

            # 获取当前会话的 sessionid
            session_id = request.session.session_key

            return Response({
                'status': 'success',
                'message': 'Login successful',
                'sessionid': session_id,  # 返回 sessionid
                'is_staff': user.is_staff,  # 返回用户是否是管理员
            }, status=status.HTTP_200_OK)
        else:
            # 增加登录失败次数
            cache.set(cache_key, failure_count + 1, timeout=600)  # 10 分钟过期
            return Response({
                'status': 'error',
                'message': 'Invalid username or password',
                'remaining_attempts': 5 - (failure_count + 1),  # 剩余尝试次数
            }, status=status.HTTP_400_BAD_REQUEST)

    return Response({
        'status': 'error',
        'message': 'Invalid request method',
    }, status=status.HTTP_405_METHOD_NOT_ALLOWED)


@api_view(['GET', 'POST'])
def if_login(request):
    if request.user.is_authenticated:
        user = request.user
        # 检查是否为管理员
        if user.is_staff:
            return Response({
                'status': 'success',
                'message': f"管理员 {user.username} 已经登录",
                'is_staff': user.is_staff,
            }, status=status.HTTP_200_OK)
        else:
            return Response({
                'status': 'error',
                'message': '用户不是管理员',
            }, status=status.HTTP_403_FORBIDDEN)
    else:
        return Response({'status': 'error', 'message': '用户未登录'}, status=status.HTTP_401_UNAUTHORIZED)


@api_view(['POST', 'GET'])
def user_logout(request):
    if request.user.is_authenticated:
        # 检查是否为管理员
        if request.user.is_staff:
            logout(request)
            return Response({
                'status': 'success',
                'message': 'Logout successful',
            }, status=status.HTTP_200_OK)
        else:
            return Response({
                'status': 'error',
                'message': '用户不是管理员，无法注销',
            }, status=status.HTTP_403_FORBIDDEN)
    else:
        return Response({'status': 'error', 'message': '用户未登录'}, status=status.HTTP_401_UNAUTHORIZED)


@api_view(['GET'])
def get_csrf_token(request):
    csrf_token = get_token(request)
    return Response({'csrfToken': csrf_token}, status=status.HTTP_200_OK)


@api_view(['POST'])
@permission_classes([IsAuthenticated])  # 确保用户已登录
def add_product(request):
    # 检查用户权限
    if not request.user.is_staff:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)
    if not request.user.is_authenticated:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)

    if request.method == 'POST':
        # 获取用户上传的图片文件
        image_file = request.FILES.get('image')
        if not image_file:
            return Response({"error": "图片文件未提供"}, status=status.HTTP_400_BAD_REQUEST)
        try:
            validate_image_file(image_file)
        except ValidationError as e:
            return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
        # 上传图片到图床
        try:
            upload_url = "https://api.superbed.cn/upload"
            token = "8f98769ca1764eada7f9284de22ecd0b"  # 替换为你的图床 Token
            files = {"file": image_file}
            data = {"token": token}
            response = requests.post(upload_url, files=files, data=data)
            response.raise_for_status()  # 检查请求是否成功
            image_url = response.json().get("url")  # 获取图床返回的图片 URL
            if not image_url:
                return Response({"error": "图床返回的 URL 无效"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        except Exception as e:
            return Response({"error": f"图片上传失败: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        # 保存图片 URL 到 Image 模型
        try:
            image = Image.objects.create(
                name=image_file.name,
                url=image_url,
                type="product_image",  # 根据需求设置图片类型
                format=image_file.name.split('.')[-1]  # 获取文件扩展名
            )
        except Exception as e:
            return Response({"error": f"保存图片信息失败: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        # 创建 Product 并关联 Image
        try:
            product_data = {
                'productname': request.POST.get('productname'),
                'description': request.POST.get('description'),
                'en_description': request.POST.get('en_description'),
                'price': request.POST.get('price'),
                'member_price': request.POST.get('memberprice'),
                'subid': request.POST.get('subid'),
                'maxtimes': request.POST.get('maxtimes'),
                'location': request.POST.get('location'),
                'covar_id': image.id,  # 关联 Image 的 ID
            }
            # print(product_data)
            serializer = ProductSerializer(data=product_data)
            if serializer.is_valid():
                product=serializer.save()
                logger.info(
                    f'产品创建成功 - '
                    f'产品ID: {product.id} | '
                    f'操作人: {request.user.username} | '
                    f'数据: {serializer.validated_data}'
                )
                # 2. 记录管理员日志（Django admin专用）
                LogEntry.objects.log_action(
                    user_id=request.user.id,
                    content_type_id=ContentType.objects.get_for_model(product).pk,
                    object_id=product.id,
                    object_repr=str(product),
                    action_flag=ADDITION,
                    change_message=f'通过API创建，数据: {serializer.validated_data}'
                )
                #    print(serializer.data)
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            else:
                #   print(serializer.errors)
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            return Response({"error": f"创建产品失败: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['PUT', 'POST'])
@permission_classes([IsAuthenticated])  # 确保用户已登录
def update_product(request, product_id):
    # 检查用户权限
    if not request.user.is_staff:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)
    if not request.user.is_authenticated:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)

    try:
        # 获取要更新的产品对象
        product = Product.objects.get(id=product_id)
    except Product.DoesNotExist:
        return Response({"detail": "Product not found"}, status=status.HTTP_404_NOT_FOUND)

    # 检查是否有图片上传
    image_file = request.FILES.get('image')
    if image_file:
        # 上传图片到图床
        try:
            validate_image_file(image_file)
        except ValidationError as e:
            return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
        try:
            print(image_file.name)
            upload_url = "https://api.superbed.cn/upload"
            token = "8f98769ca1764eada7f9284de22ecd0b"  # 替换为你的图床 Token
            files = {"file": image_file}
            data = {"token": token}
            response = requests.post(upload_url, files=files, data=data)
            response.raise_for_status()  # 检查请求是否成功
            image_url = response.json().get("url")  # 获取图床返回的图片 URL
            if not image_url:
                return Response({"error": "图床返回的 URL 无效"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        except Exception as e:
            return Response({"error": f"图片上传失败: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        # 保存图片 URL 到 Image 模型
        try:
            image = Image.objects.create(
                name=image_file.name,
                url=image_url,
                type="product_image",  # 根据需求设置图片类型
                format=image_file.name.split('.')[-1]  # 获取文件扩展名
            )
        except Exception as e:
            return Response({"error": f"保存图片信息失败: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        # 更新产品的封面图片
        product.covar_id = image

    # 更新其他字段
    product_data = {
        'productname': request.data.get('productname', product.productname),
        'description': request.data.get('description', product.description),
        'en_description': request.data.get('en_description', product.en_description),
        'price': request.data.get('price', product.price),
        'member_price': request.data.get('member_price', product.member_price),
        'subid': request.data.get('subid', product.subid),
        'maxtimes': request.data.get('maxtimes', product.maxtimes),
        'location': request.data.get('location', product.location),
    }

    # 使用序列化器更新数据
    serializer = ProductSerializer(product, data=product_data, partial=True)
    # print((product_data))
    if serializer.is_valid():
        serializer.save()
        logger.info(
            f'产品修改成功 - '
            f'产品ID: {product.id} | '
            f'操作人: {request.user.username} | '
            f'数据: {serializer.validated_data}'
        )
        # 2. 记录管理员日志（Django admin专用）
        LogEntry.objects.log_action(
            user_id=request.user.id,
            content_type_id=ContentType.objects.get_for_model(product).pk,
            object_id=product.id,
            object_repr=str(product),
            action_flag=ADDITION,
            change_message=f'通过API修改，数据: {serializer.validated_data}'
        )
        return Response(serializer.data, status=status.HTTP_200_OK)

    # 如果数据无效，返回错误信息
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(['DELETE'])
@permission_classes([IsAuthenticated])
def delete_product(request, product_id):
    """
    根据商品ID删除商品（及关联的图片）
    权限要求：管理员/staff用户
    """
    # 检查用户权限
    if not request.user.is_staff:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)
    if not request.user.is_authenticated:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)
    try:
        # 获取要删除的商品
        product = Product.objects.get(id=product_id)
        # 删除商品
        product.delete()
        logger.info(
            f'产品删除成功 - '
            f'产品ID: {product_id} | '
            f'操作人: {request.user.username} | '
        )
        return Response(
            {'status': 'success', 'message': f'商品ID {product_id} 删除成功'},
            status=status.HTTP_200_OK
        )

    except Product.DoesNotExist:
        return Response(
            {'status': 'error', 'message': f'商品ID {product_id} 不存在'},
            status=status.HTTP_404_NOT_FOUND
        )
    except Exception as e:
        return Response(
            {'status': 'error', 'message': f'删除失败: {str(e)}'},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def coach_list(request):
    if not request.user.is_authenticated or not request.user.is_staff:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)

    try:
        search = request.GET.get('search', '')
        page = int(request.GET.get('page', 1))
        page_size = int(request.GET.get('page_size', 10))  # 默认 10 条/页

        queryset = Coach.objects.select_related('cover_image').order_by('id')
        if search:
            queryset = queryset.filter(name__icontains=search)

        total_items = queryset.count()
        total_pages = ceil(total_items / page_size)  # 计算总页数
        # 特判：如果数据量正好等于 page_size，则只有第 1 页有数据
        if total_items == page_size and page > 1:
            return Response({
                "count": total_items,
                "total_pages": 1,  # 只有 1 页
                "current_page": page,
                "has_next": False,
                "has_previous": page > 1,
                "results": []  # 返回空列表
            })

        # 正常分页逻辑
        paginator = Paginator(queryset, page_size)
        page_data = paginator.get_page(page)

        results = []
        for coach in page_data:
            results.append({
                'id': coach.id,
                'name': coach.name,
                'tags': coach.tags,
                'tags_array': [tag.strip() for tag in re.split(r'[,，]', coach.tags) if tag.strip()],
                'cover_image': {'url': coach.cover_image.url if coach.cover_image else None},
                'wechat_id': coach.wechat_id,
                'phone_number': coach.phone_number
            })

        return Response({
            "count": total_items,
            "total_pages": total_pages,
            "current_page": page_data.number,
            "has_next": page_data.has_next(),
            "has_previous": page_data.has_previous(),
            "results": results
        })

    except Exception as e:
        print(f"Error: {e}")
        return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def coach_detail(request, coach_id):
    """
    获取教练详情 (管理员权限)
    路由: GET /api/admin/coaches/<int:coach_id>/
    """
    # 验证管理员权限
    if not request.user.is_staff:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)
    if not request.user.is_authenticated:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)

    try:
        coach = get_object_or_404(Coach.objects.select_related('cover_image'), pk=coach_id)
        print(coach_id)
        # 构建响应数据
        data = {
            'id': coach.id,
            'name': coach.name,
            'birth_date': coach.birth_date.strftime('%Y-%m-%d') if coach.birth_date else None,
            'age': calculate_age(coach.birth_date) if coach.birth_date else None,
            'description': coach.description,
            'en_description': coach.en_description,
            'phone_number': coach.phone_number,
            'wechat_id': coach.wechat_id,
            'tags': coach.tags,
            'tags_array': coach.get_tags_list(),
            'created_at': coach.created_at.strftime('%Y-%m-%d %H:%M:%S'),
            'updated_at': coach.updated_at.strftime('%Y-%m-%d %H:%M:%S'),
            'cover_image': {
                'id': coach.cover_image.id if coach.cover_image else None,
                'url': coach.cover_image.url if coach.cover_image else None,
                'name': coach.cover_image.name if coach.cover_image else None
            } if coach.cover_image else None,
        }

        return Response({'status': 'success', 'data': data})

    except Exception as e:
        print(e)
        return Response(
            {'status': 'error', 'message': str(e)},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )


def calculate_age(birth_date):
    today = timezone.now().date()  # 获取今天的日期
    age = today.year - birth_date.year  # 基础年龄
    # 如果今天的月份和日期小于出生日期，则年龄减去1
    if (today.month, today.day) < (birth_date.month, birth_date.day):
        age -= 1
    return age
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def add_coach(request):
    # 检查用户权限
    if not request.user.is_staff:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)
    if not request.user.is_authenticated:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)

    if request.method == 'POST':
        # 1. 处理封面照片
        cover_image_file = request.FILES.get('image')
        if not cover_image_file:
            return Response({"error": "封面图片未提供"}, status=status.HTTP_400_BAD_REQUEST)

        # 2. 获取表单数据
        tags = request.POST.get('tags', '').replace('，', ',')
        coach_data = {
            'name': request.POST.get('name'),
            'birth_date': request.POST.get('birth_date'),
            'description': request.POST.get('description'),
            'en_description': request.POST.get('en_description'),
            'phone_number': request.POST.get('phone_number'),
            'wechat_id': request.POST.get('wechat_id'),
            'tags': tags,
        }
        try:
            validate_image_file(cover_image_file)
        except ValidationError as e:
            return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
        try:
            # 3. 上传封面图片到图床
            cover_image_url = upload_to_image_bed(cover_image_file)
            cover_image = Image.objects.create(
                name=f"cover_{coach_data['name']}",
                url=cover_image_url,
                type=f"coach_cover",
                format=cover_image_file.name.split('.')[-1]
            )
            coach_data['cover_image_id'] = cover_image.id

            # 4. 创建教练记录
            serializer = CoachSerializer(data=coach_data)
            if not serializer.is_valid():
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

            coach = serializer.save()
            # 5. 记录管理员日志
            LogEntry.objects.log_action(
                user_id=request.user.id,
                content_type_id=ContentType.objects.get_for_model(coach).pk,
                object_id=coach.id,
                object_repr=str(coach),
                action_flag=ADDITION,
                change_message=f'通过API创建，数据: {serializer.validated_data}'
            )

            return Response(serializer.data, status=status.HTTP_201_CREATED)

        except ValidationError as e:
            return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
        except requests.exceptions.RequestException as e:
            return Response({"error": f"图片上传失败: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        except Exception as e:
            return Response({"error": f"创建教练失败: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


def upload_to_image_bed(image_file):
    """上传图片到图床的通用函数"""
    upload_url = "https://api.superbed.cn/upload"
    token = "8f98769ca1764eada7f9284de22ecd0b"  # 替换为你的图床 Token
    files = {"file": image_file}
    data = {"token": token}

    response = requests.post(upload_url, files=files, data=data)
    response.raise_for_status()

    image_url = response.json().get("url")
    if not image_url:
        raise Exception("图床返回的URL无效")
    return image_url


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_coach_photos(request, coach_id):
    if not request.user.is_staff:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)
    if not request.user.is_authenticated:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)

    try:
        # 构建要查询的 type 值
        coach_type = f'coach_{coach_id}_photo'
        # 查询并按 id 排序
        images = Image.objects.filter(
            type=coach_type
        ).order_by('id').values('url')

        # 提取 URL 列表
        photo_urls = [img['url'] for img in images]
        return Response({
            'coach_id': coach_id,
            'photo_urls': photo_urls,
            'count': len(photo_urls)
        }, status=status.HTTP_200_OK)

    except Exception as e:
        return Response({
            'error': str(e)
        }, status=status.HTTP_400_BAD_REQUEST)


@api_view(['POST'])
@permission_classes([IsAuthenticated])
def add_coach_photos(request, coach_id):
    if not request.user.is_staff:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)
    if not request.user.is_authenticated:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)
    photo_file = request.FILES.get('photo')
    if not photo_file:
        return Response({"error": "照片文件未提供"}, status=status.HTTP_400_BAD_REQUEST)
    try:
        validate_image_file(photo_file)
    except ValidationError as e:
        return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
    try:
        # 上传到图床
        photo_url = upload_to_image_bed(photo_file)
        # 创建图片记录，使用type字段存储关联关系
        Image.objects.create(
            name=f"photo_{coach_id}_{photo_file.name}",
            url=photo_url,
            type=f"coach_{coach_id}_photo",  # 用type字段存储关联信息
            format=photo_file.name.split('.')[-1]
        )
        return Response({"status": "success"}, status=status.HTTP_201_CREATED)
    except Exception as e:
        print(e)
        return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['DELETE'])
@permission_classes([IsAuthenticated])
def delete_coach(request, coach_id):
    # 权限检查：只有管理员可以删除
    if not request.user.is_staff:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)
    if not request.user.is_authenticated:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)

    print(coach_id, request)
    try:
        # 1. 获取教练对象
        coach = Coach.objects.get(id=coach_id)

        # 2. 记录日志（在删除前获取必要信息）
        log_entry_message = f"删除教练: {coach.name} (ID: {coach.id})，关联图片: "

        # 3. 查找所有关联图片（封面图 + 多张照片）
        # 封面图（通过 cover_image_id 关联）
        cover_images = Image.objects.filter(id=coach.cover_image_id)
        # 其他照片（通过 type 字段匹配，如 "coach_1_photo"）
        coach_photos = Image.objects.filter(type__startswith=f"coach_{coach_id}_")

        all_images = list(cover_images) + list(coach_photos)
        log_entry_message += f"共 {len(all_images)} 张"

        # 4. 删除所有关联图片（先删图片记录，再实际从图床删除）
        deleted_image_urls = []
        for image in all_images:
            deleted_image_urls.append(image.url)
            image.delete()  # 删除数据库记录

        # （可选）在这里添加从图床实际删除文件的逻辑
        # delete_images_from_bed(deleted_image_urls)

        # 5. 删除教练记录
        coach_name = str(coach)  # 用于日志记录
        coach.delete()

        # 6. 记录管理员操作日志
        LogEntry.objects.log_action(
            user_id=request.user.id,
            content_type_id=ContentType.objects.get_for_model(Coach).pk,
            object_id=coach_id,
            object_repr=coach_name,
            action_flag=DELETION,
            change_message=log_entry_message
        )

        return Response(
            {"status": "success", "message": f"教练 {coach_name} 及其 {len(all_images)} 张图片已删除"},
            status=status.HTTP_200_OK
        )

    except Coach.DoesNotExist:
        return Response(
            {"error": "教练不存在"},
            status=status.HTTP_404_NOT_FOUND
        )
    except Exception as e:
        return Response(
            {"error": f"删除失败: {str(e)}"},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )


@api_view(['POST'])
@permission_classes([IsAuthenticated])
def upload_coach_image(request):
    """
    上传教练图片到图床
    POST /api/admin/upload_coach_image/
    参数:
    - image: 图片文件 (注意前端字段名应为image而不是photo)
    - coach_id: 教练ID
    - is_cover: 是否设为封面图 (true/false)
    """
    if not request.user.is_staff:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)
    if not request.user.is_authenticated:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)


    try:
        coach_id = request.POST.get('coach_id')
        is_cover = request.POST.get('is_cover', 'false').lower() == 'true'
        photo_file = request.FILES.get('image')
        print(is_cover)
        print(not is_cover)
        # 参数校验
        if not coach_id or not coach_id.isdigit():
            return Response(
                {'status': 'error', 'message': '无效的教练ID'},
                status=status.HTTP_400_BAD_REQUEST
            )

        if not photo_file:
            return Response(
                {'status': 'error', 'message': '照片文件未提供'},
                status=status.HTTP_400_BAD_REQUEST
            )

        coach_id = int(coach_id)
        try:
            validate_image_file(photo_file)
        except ValidationError as e:
            return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
        # 校验非封面图片数量（不超过5张）
        image_type=f"coach_cover"
        if not is_cover:
            image_type = f"coach_{coach_id}_photo"
            existing_images_count = Image.objects.filter(
                type=image_type
            ).exclude(
                id__in=Coach.objects.filter(cover_image__isnull=False)
                .values_list('cover_image__id', flat=True)
            ).count()

            if existing_images_count >= 9:
                return Response(
                    {
                        'status': 'error',
                        'message': '每个教练最多只能上传5张非封面图片'
                    },
                    status=status.HTTP_400_BAD_REQUEST
                )
        # 检查教练是否存在
        Coach.objects.get(id=coach_id)
        # 上传到图床
        photo_url = upload_to_image_bed(photo_file)
        # 创建图片记录
        image = Image.objects.create(
            name=f"coach_{coach_id}_photo_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
            url=photo_url,
            type=image_type,
            format=photo_file.name.split('.')[-1].lower()
        )
        # 如果是封面图，更新教练记录
        if is_cover:
            # 先取消现有的封面图
            Coach.objects.filter(cover_image__type=image_type).update(cover_image=None)
            print("!2343543")
            # 设置新封面图
            coach = Coach.objects.get(id=coach_id)
            old_cover = coach.cover_image
            coach.cover_image = image
            coach.save()

            # 记录封面变更日志
            LogEntry.objects.log_action(
                user_id=request.user.id,
                content_type_id=ContentType.objects.get_for_model(coach).pk,
                object_id=coach.id,
                object_repr=str(coach),
                action_flag=CHANGE,
                change_message=(
                    f'更新封面图片: {old_cover.url if old_cover else "无"} → {photo_url}'
                )
            )

        # 记录图片上传日志
        LogEntry.objects.log_action(
            user_id=request.user.id,
            content_type_id=ContentType.objects.get_for_model(image).pk,
            object_id=image.id,
            object_repr=str(image),
            action_flag=ADDITION,
            change_message=f'上传{"封面" if is_cover else ""}图片，教练ID: {coach_id}'
        )

        return Response({
            'status': 'success',
            'message': '图片上传成功',
            'data': {
                'image_url': photo_url,
                'image_id': image.id,
                'is_cover': is_cover
            }
        })

    except Coach.DoesNotExist:
        return Response(
            {'status': 'error', 'message': '教练不存在'},
            status=status.HTTP_404_NOT_FOUND
        )
    except Exception as e:
        print(e)
        # 记录错误日志
        LogEntry.objects.log_action(
            user_id=request.user.id,
            content_type_id=ContentType.objects.get_for_model(Image).pk,
            object_id=0,
            object_repr=f"Coach Image Upload Error",
            action_flag=CHANGE,
            change_message=f'上传教练图片失败: {str(e)}'
        )
        return Response(
            {'status': 'error', 'message': '图片上传失败: ' + str(e)},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def set_coach_cover(request):
    """
    设置教练封面图
    POST /api/admin/set_coach_cover/
    参数:
    - image_url: 图片URL
    - coach_id: 教练ID
    """
    if not request.user.is_staff:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)
    if not request.user.is_authenticated:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)

    try:
        coach_id = request.data.get('coach_id')
        image_url = request.data.get('image_url')

        coach = Coach.objects.get(id=coach_id)
        image = Image.objects.get(url=image_url)

        # 更新封面图
        old_cover = coach.cover_image
        coach.cover_image = image
        coach.save()

        # 记录日志
        LogEntry.objects.log_action(
            user_id=request.user.id,
            content_type_id=ContentType.objects.get_for_model(coach).pk,
            object_id=coach.id,
            object_repr=str(coach),
            action_flag=CHANGE,
            change_message=f'更改封面图: 从 {old_cover.url if old_cover else "无"} 改为 {image_url}'
        )

        return Response({'status': 'success'})

    except ObjectDoesNotExist:
        return Response({'status': 'error', 'message': '教练或图片不存在'}, status=404)
    except Exception as e:
        return Response({'status': 'error', 'message': str(e)}, status=500)

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def delete_coach_image(request):
    """
    删除教练图片
    POST /api/admin/delete_coach_image/
    参数:
    - image_url: 图片URL
    - coach_id: 教练ID
    """
    if not request.user.is_staff:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)
    if not request.user.is_authenticated:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)

    try:
        image_url = request.data.get('image_url')
        coach_id = request.data.get('coach_id')
        # 查找图片
        image = Image.objects.get(url=image_url)
        # 检查是否是封面图
        coach = Coach.objects.get(id=coach_id)
        is_cover = coach.cover_image and coach.cover_image.url == image_url
        # 如果是封面图，先取消关联
        if is_cover:
            coach.cover_image = None
            coach.save()

        # 记录日志
        LogEntry.objects.log_action(
            user_id=request.user.id,
            content_type_id=ContentType.objects.get_for_model(image).pk,
            object_id=image.id,
            object_repr=str(image),
            action_flag=DELETION,
            change_message=f'删除教练图片，教练ID: {coach_id}' + (' (封面图)' if is_cover else '')
        )

        if is_cover:
            LogEntry.objects.log_action(
                user_id=request.user.id,
                content_type_id=ContentType.objects.get_for_model(coach).pk,
                object_id=coach.id,
                object_repr=str(coach),
                action_flag=CHANGE,
                change_message=f'移除封面图片: {image_url}'
            )

        # 删除记录
        image.delete()

        # 注意：这里不删除图床上的实际文件，如需删除需要调用图床API
        # delete_from_image_bed(image_url)

        return Response({'status': 'success'})

    except ObjectDoesNotExist:
        return Response({'status': 'error', 'message': '图片不存在'}, status=404)
    except Exception as e:
        print(e)
        return Response({'status': 'error', 'message': str(e)}, status=500)


@api_view(['PUT'])
@permission_classes([IsAuthenticated])
def update_coach(request, coach_id):
    if not request.user.is_staff:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)
    if not request.user.is_authenticated:
        return Response({'status': 'error', 'message': 'Permission denied'}, status=403)
    try:
        coach = Coach.objects.get(id=coach_id)

        # 深拷贝旧数据用于日志记录
        import copy
        old_coach = copy.deepcopy(coach)

        # 部分更新
        serializer = CoachSerializer(coach, data=request.data, partial=True)

        if not serializer.is_valid():
            return Response(
                {'status': 'error', 'message': serializer.errors},
                status=status.HTTP_400_BAD_REQUEST
            )

        serializer.save()

        # 准备变更日志
        change_message = []
        fields_to_check = [
            'name', 'phone_number', 'wechat_id',
            'description', 'tags', 'birth_date',
            'en_description'
        ]

        for field in fields_to_check:
            old_value = getattr(old_coach, field)
            new_value = getattr(coach, field)

            if old_value != new_value:
                # 处理日期等特殊字段的显示
                if field == 'birth_date':
                    old_value = old_value.strftime('%Y-%m-%d') if old_value else None
                    new_value = new_value.strftime('%Y-%m-%d') if new_value else None

                change_message.append(
                    f"{Coach._meta.get_field(field).verbose_name}: "
                    f"{old_value} → {new_value}"
                )

        # 如果有变更则记录日志
        if change_message:
            LogEntry.objects.log_action(
                user_id=request.user.id,
                content_type_id=ContentType.objects.get_for_model(Coach).pk,
                object_id=coach.id,
                object_repr=str(coach),
                action_flag=CHANGE,
                change_message='教练信息更新:\n' + '\n'.join(change_message)
            )

        # 返回更新后的完整数据
        return Response({
            'status': 'success',
            'message': '更新成功',
            'data': CoachSerializer(coach).data
        })

    except Coach.DoesNotExist:
        return Response(
            {'status': 'error', 'message': '教练不存在'},
            status=status.HTTP_404_NOT_FOUND
        )
    except Exception as e:
        # 记录错误日志
        LogEntry.objects.log_action(
            user_id=request.user.id,
            content_type_id=ContentType.objects.get_for_model(Coach).pk,
            object_id=coach_id,
            object_repr=f"Coach ID: {coach_id}",
            action_flag=CHANGE,
            change_message=f'更新教练信息失败: {str(e)}'
        )
        return Response(
            {'status': 'error', 'message': '服务器内部错误'},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )